﻿// --------------------------------------------------------------------------------------------------------------------- 
// <copyright file="CreateSite.cs" company="Collaboris Ltd.">
//   Copyright (c) Collaboris Ltd. All rights Reserved.
// </copyright>
// <summary>
//   Defines an Action to create a new site Collection.
// </summary>
// ---------------------------------------------------------------------------------------------------------------------
namespace Collaboris.Saf.Actions.Wss.Site
{
    using System;

    using Engine;

    using Entities;

    using Microsoft.SharePoint;
    using Microsoft.SharePoint.Administration;

    using SharePoint.Wss.Administraton;
    using SharePoint.Wss.Attributes;
    using SharePoint.Wss.Sites;
    using SharePoint.Wss.WebApplications;

    using Utils;

    [CollaborisClass(
        Title = "Create Site",
        ReleaseStatus = ReleaseStatus.Beta,
        DisableDocumentation = false,
        ContactAuthorEmail = "Support@Collaboris.co.uk",
        Summary = "Creates (or overwrites) a site collection (SPSite) in a web application.",
        UndoImplemented = true,
        ClassGuid = "{156E17A5-A7BA-4e1f-8A68-1BC341A7C657}")]
    public class CreateSite : WSSActionBase<SiteInfo>
    {

        private SPWebApplication webApp;

        /// <summary>
        /// Does the action.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="entity">The entity.</param>
        /// <returns></returns>
        protected override ProcessStatus DoAction(SafContext context, SiteInfo entity)
        {
            this.Trace.TraceMethodStart("DoAction");

            SPWebApplication activeWebApplication = this.ConfigureParentWebApp(entity);

            SPSiteHelper.CreateSite(
                    activeWebApplication,
                    entity.Overwrite,
                    entity.SiteCollectionUrl,
                    entity.Title,
                    entity.Description,
                    entity.LocaleId,
                    entity.WebTemplate,
                    entity.OwnerLogin,
                    entity.OwnerName,
                    entity.OwnerEmail,
                    entity.SecondaryContactLogin,
                    entity.SecondaryContactName,
                    entity.SecondaryContactEmail,
                    entity.DatabaseServer,
                    entity.DatabaseName,
                    entity.DatabaseUserName,
                    entity.DatabasePassword,
                    entity.UseHostHeaderAsSiteName);

            if (!SPSiteHelper.SiteExists(entity.SiteCollectionUrl, activeWebApplication))
            {
                throw new ApplicationException(string.Format("This Site was not created : '{0}'", entity.SiteCollectionUrl));
            }

            this.Trace.TraceMethodEnd("DoAction");

            return ProcessStatus.Success;
        }

        private SPWebApplication ConfigureParentWebApp(SiteInfo entity)
        {
            // now lets decide which Web app we gonna use
            SPWebApplication activeWebApplication;
            if (!string.IsNullOrEmpty(entity.WebApplicationUrl))
            {
                this.Trace.TraceInfo("Attempting to bind to an SPWebApplication, for this url : '" + entity.WebApplicationUrl + "'");
                activeWebApplication = SPWebApplicationHelper.GetWebAppFromUrl(entity.WebApplicationUrl);
                if (activeWebApplication == null)
                {
                    throw new NullReferenceException("Unable to return a Web application for this url : '" + entity.WebApplicationUrl + "'");
                }                    
            }
            else
            {
                this.Trace.TraceInfo("Using the Context for the current Web Application");
                activeWebApplication = this.TargetWeb.Site.WebApplication;
                this.webApp = this.TargetWeb.Site.WebApplication;
            }

            this.ConfigLocaleId(entity, activeWebApplication);

            return activeWebApplication;
        }

        /// <summary>
        /// Configs the locale id.
        /// </summary>
        /// <param name="entity">The entity.</param>
        /// <param name="webApp">The web app.</param>
        private void ConfigLocaleId(SiteInfo entity, SPWebApplication webApp)
        {
            TraceHelper.TraceMethodStart(TraceSwitch, "CreateSite", "ConfigLocaleId");
            if (entity.LocaleId < 1)
            {
                try
                {
                    if (webApp != null)
                    {
                        if (webApp.Sites.Count > 0)
                        {
                            using (SPWeb web = webApp.Sites[0].RootWeb)
                            {
                                TraceHelper.TraceVerbose(
                                    TraceSwitch,
                                    "CreateSite",
                                    "Attempting to find the LocaleId, for the Root Web in the First site");

                                entity.LocaleId = SPRegionalSettingsHelper.GetLocaleId(web);
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    TraceHelper.TraceException(TraceSwitch, "CreateSite", "DoAction", ex);
                    entity.LocaleId = 1033;
                }
            }

            TraceHelper.TraceMethodEnd(TraceSwitch, "CreateSite", "ConfigLocaleId");
        }

        /// <summary>
        /// Always deletes the Site as specified by the entity.Url
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="entity">The entity.</param>
        /// <returns></returns>
        protected override ProcessStatus UndoAction(SafContext context, SiteInfo entity)
        {
            this.Trace.TraceMethodStart("UndoAction");
            
            SPWebApplication activeWebApplication = this.ConfigureParentWebApp(entity);

            SPSiteHelper.DeleteSiteCollection(activeWebApplication, entity.SiteCollectionUrl);
            
            this.Trace.TraceMethodEnd("UndoAction");

            return ProcessStatus.Success;
        }

        /// <summary>
        /// Checks the Data entity used by the Action for Validity
        /// </summary>
        /// <param name="context">The <see cref="SafContext"/> passed in by the SAF Engine.</param>
        /// <param name="entity">The data entity to Validate.</param>
        /// <param name="errors">List of <see cref="ValidationError"/>s</param>
        /// <param name="mode"><see cref="ProcessMode"/>signalling wheter we are Doing, or Undoing the action.</param>
        /// <returns>false if invalid; otherwise true.</returns>
        protected override bool IsValid(
                                        SafContext context,
                                        SiteInfo entity,
                                        ref System.Collections.Generic.List<ValidationError> errors,
                                        ProcessMode mode)
        {
            int currentCount = errors.Count;

            // Validate each object now.
            ValidateStringForNull(entity.OwnerEmail, "SiteInfo.OwnerEmail", ref errors);
            ValidateStringForNull(entity.OwnerLogin, "SiteInfo.OwnerLogin", ref errors);


            if (!string.IsNullOrEmpty(entity.SecondaryContactLogin))
            {
                ValidateStringForNull(entity.SecondaryContactName, "SiteInfo.SecondaryContactName", ref errors);
                ValidateStringForNull(entity.SecondaryContactEmail, "SiteInfo.SecondaryContactEmail", ref errors);
            }

            ValidateStringForNull(entity.SiteCollectionUrl, "SiteInfo.Url", ref errors);
            ValidateStringForNull(entity.WebTemplate, "SiteInfo.WebTemplate", ref errors);

            // Have we added errors ?
            return errors.Count == currentCount;
        }
    }
}
